#pragma once
#include "RBT.hpp"
#include <iostream>
#include <vector>

using std::vector;
using std::endl;
using std::cout;
namespace my_map
{
	using namespace my_rbt;
	template<typename K, typename Val>
	struct KeyOfVal
	{
		const K& operator()(const Val& val) const
		{
			return val.first;
		}
	};

	template<typename K, typename V>
	class map
	{
	public:
		// 使用模板类内的类型 需要使用typename指名 是模板类内的类型
		typedef typename RBTree<K, std::pair<const K, V>, KeyOfVal<K, std::pair<const K, V>>>::iterator  iterator;
		typedef typename RBTree<K, std::pair<const K, V>, KeyOfVal<K, std::pair<const K, V>>>::const_iterator const_iterator;
		typedef map<K, V> Self;
		typedef RBTree<K, std::pair<const K, V>, KeyOfVal<K, std::pair<const K, V>>> RBTree_;
		map()
		{}
		map(Self& m)
		{
			cout << "map(Self& m)" << endl;
			_rbt = m._rbt;
		}


		// 模板类中的&& 是 右值引用
		map(Self&& m)
		{
			cout << "map( Self&& m)" << endl;
			_rbt = std::forward<RBTree_>(m._rbt);

		}
		// const 对象 是不可能调用 operator =
		// const 成员函数，指的是在这个函数中不能修改类的成员变量
		Self& operator=(Self&& m)
		{
			cout << "Self& operator=(Self&& m)" << endl;
			_rbt = std::forward<RBTree_>(m._rbt);
			return *this;
		}
		Self& operator=(Self& m)
		{
			cout << "Self& operator=(Self& m)" << endl;
			_rbt = m._rbt;
			return *this;
		}


		std::pair<iterator, bool> insert(std::pair<K, V> kv)
		{
			return _rbt.insert(kv);

		}
		V& operator[](const K& key)
		{
			auto res = _rbt.insert(make_pair(key, V()));
			return (res.first)->second;
		}
		iterator find(const K& key)
		{
			auto res = _rbt.find(key);
			return res.first;
		}

		iterator begin()
		{
			//cout << "iterator begin()" << endl;

			return _rbt.begin();
		}

		iterator end()
		{
			//cout << "iterator end()" << endl;

			return _rbt.end();
		}
		const_iterator begin() const
		{
			cout << "const_iterator begin() const" << endl;
			return _rbt.begin();
		}
		const_iterator end() const
		{

			return _rbt.end();
		}
		iterator last()
		{
			return _rbt.last();
		}
		const_iterator last() const
		{
			return _rbt.last();
		}

	public:
		// map 中key是不能修改的
		RBTree_ _rbt;
	};


	void test_map1()
	{
		map<int, int> mp;
		vector<int> v({ 16, 3, 7, 11, 9, 26, 18, 14, 15 });
		for (int i = 0; i < v.size(); i++)
		{
			mp.insert(std::make_pair(v[i], v[i]));
		}
		cout << mp._rbt.IsRBTree() << endl;
		mp._rbt.PreOrder();
		auto it = mp.begin();
		while (it != mp.end())
		{
			cout << it->first << " ";
			++it;
		}
		cout << endl;
		auto pos = mp.find(16);
		while (pos != mp.end())
		{
			cout << pos->first << " ";
			++pos;
		}

	}
	void test_map2()
	{
		map<int, int> mp;
		vector<int> v({ 16, 3, 7, 11, 9, 26, 18, 14, 15 });
		for (int i = 0; i < v.size(); i++)
		{
			mp.insert(std::make_pair(v[i], v[i]));
		}
		map<int, int> mp2(mp);
		auto it = mp2.begin();
		while (it != mp2.end())
		{
			cout << it->first << " ";
			++it;
		}
		cout << endl << "-----------------" << endl;


		map<int, int> mp3(std::move(mp));
		it = mp3.begin();
		while (it != mp3.end())
		{
			cout << it->first << " ";
			++it;
		}

		cout << endl << "-----------------" << endl;

		map<int, int> mp4;
		mp4 = mp2;
		it = mp4.begin();
		while (it != mp4.end())
		{
			cout << it->first << " ";
			++it;
		}
		cout << endl << "-----------------" << endl;


		map<int, int> mp5;
		mp5 = std::move(mp2);
		it = mp5.begin();
		while (it != mp5.end())
		{
			cout << it->first << " ";
			++it;
		}
	}
	void test_const(const map<int, int>& m)
	{
		auto it = m.begin();
		while (it != m.end())
		{
			cout << it->first << " ";
			++it;
		}
	}
	void test_map3()
	{
		map<int, int> mp;
		vector<int> v({ 16, 3, 7, 11, 9, 26, 18, 14, 15 });
		for (int i = 0; i < v.size(); i++)
		{
			mp.insert(std::make_pair(v[i], v[i]));
		}
		mp[29] = 29;
		test_const(mp);
	}

	void test_map4()
	{
		map<int, int> mp;
		vector<int> v({ 16, 3, 7, 11, 9, 26, 18, 14, 15 });
		for (int i = 0; i < v.size(); i++)
		{
			mp.insert(std::make_pair(v[i], v[i]));
		}
		mp[29] = 29;

		auto last = mp.last();
		while (last != mp.end())
		{
			cout << last->first << " ";
			--last;
		}
		cout << endl << "-----------------" << endl;
		auto it = mp.begin();
		while (it != mp.end())
		{
			cout << it->first << " ";
			++it;
		}
	}
}